import random, math

from django.contrib.gis.db import models #question whether or not this geo model is necessary

#from django.contrib.gis.geos import Point, MultiPoint
from django.contrib.gis.geos.point import Point
from django.contrib.gis.geos.collections import MultiPoint
from django.contrib import admin


	
class OpenError(models.Model):
	point = models.PointField()
	objects = models.GeoManager()
	
	class Meta:
		abstract = True

	def __unicode__(self):
		return "openerror object" 
        
	def metersInLat(self):
		# create a model for this function
		return 111132;
    
	def metersInLon(self, lat):
		# do a type check
		# do a check to make sure that the lat < 90
		if lat > 89:
			lat = 89;
		return math.cos(lat) * self.metersInLat();
	
	def getClassName(self):
		return OpenError
	#
	# this function calculates the distances from each point to all the others and organizes them in a 2D list
	#
	def getDistanceMatrix(self):
		CurrClass = self.getClassName()
		all_pts = CurrClass.objects.all()
		list1 = []
		
		for pt in all_pts:
			curr_list = []
			for p in CurrClass.objects.distance(pt.point):
				curr_list.append(p.distance.m)
			
			list1.append( curr_list )
		
		return list1
		
	#
	# create_random_pt
	# used to generate a point of latitude and longitude within a normal distribution
	def createRandomPt(self):
		standard_deviation = 1
		lat = random.normalvariate(0,standard_deviation)
		lon = random.normalvariate(0,standard_deviation)
		return Point(lat, lon)
		
	#
	# first real attempt at creating the IDW function
	#
	def randomizeDataSet(self):
		"""
		edit a set of points by offsetting them with random errors 
		"""
		correlated = True
		k = 2
		
		#calculate the distances from each point to one another
		distances = self.getDistanceMatrix()
    	
		final_points = []
		# look into type checking
		if correlated:
			sigma_points = []
			count = 0
        	
			for pts in self.getClassName().objects.all():     
				rand_point = self.createRandomPt()
				if count == 0:
					# the first point has no other points to calculate distances
					
					# this stores the random offset used for the first point
					sigma_points.append( [rand_point.x, rand_point.y] ) 
					
					a = pts.point.get_x()
					b = rand_point.y
					new_point = [ pts.point.get_x() + rand_point.x, pts.point.get_y() + rand_point.y ]
					final_points.append( new_point ) # this stores the final point to be used
				else:
					
					# calculate the total weights for all the points with random points generated
					total_weights = 0
					for i in xrange( count - 1 ):
						total_weights += (1 / math.pow( distances[count][i], k) )
					
					# 
					z_lat = 0
					z_lon = 0
					

					for i in xrange( count - 1 ):
						weight = (1 / math.pow( distances[count][i], k) )
						z_lat += ( sigma_points[i][0] * weight )
						z_lon += ( sigma_points[i][1] * weight )
						
					rand_point.set_x( rand_point.x + z_lat )
					rand_point.set_y( rand_point.y + z_lon )
					
					sigma_points.append( [rand_point.get_x(), rand_point.get_y() ] )
						
					new_point = [ pts.point.get_x() + rand_point.x, pts.point.get_y() + rand_point.y ]
					final_points.append( new_point )
						
						
				count = count + 1
		
       # else:
		return final_points
    
admin.site.register(OpenError)



# ------Inherited class using OpenError class ---------------------------------------

class ImgLocations(OpenError):
	
	class Meta:
		abstract = False
		
	# redefine the current class name to return the objects of the inherited class
	def getClassName(self):
		return ImgLocations
	
	def __unicode__(self):
		return "imglocation object" 
		
admin.site.register(ImgLocations)
